#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "opencv/cv.h"
#include "opencv/highgui.h"


#ifdef WIN32
#ifdef _DEBUG
#pragma comment(lib, "opencv_core310d.lib")
#pragma comment(lib, "opencv_imgproc310d.lib")
#pragma comment(lib, "opencv_flann310d.lib")
#pragma comment(lib, "opencv_highgui310d.lib")
#pragma comment(lib, "opencv_calib3d310d.lib")
#pragma comment(lib, "opencv_videoio310d.lib")
#pragma comment(lib, "opencv_imgcodecs310d.lib")
#pragma comment(lib, "opencv_objdetect310d.lib")
#else
#pragma comment(lib, "opencv_core310.lib")
#pragma comment(lib, "opencv_imgproc310.lib")
#pragma comment(lib, "opencv_flann310.lib")
#pragma comment(lib, "opencv_highgui310.lib")
#pragma comment(lib, "opencv_features2d310.lib")
#pragma comment(lib, "opencv_video310.lib")
#pragma comment(lib, "opencv_calib3d310.lib")
#pragma comment(lib, "opencv_videoio310.lib")
#pragma comment(lib, "opencv_imgcodecs310.lib")
#pragma comment(lib, "opencv_viz310.lib")
#pragma comment(lib, "opencv_objdetect310.lib")
#endif
#endif

#define STR_LABEL_LIST          "labels.txt"
#define STR_NEGATIVE_LIST       "negative.txt"
#define STR_OUTPUT_SAMPLE       "car_samples_test_0402.dat"
#define MAX_LINE                1024

#if 0
static int32_t parse_line(const char *p_line_buf, vector<CvRect> &labels)
{
    char filename[MAX_LINE];
    int32_t num, n;

    int32_t iread = sscanf(p_line_buf, "%s %d", filename, &num);

    for (n = 0; n < num; n++) {
        int32_t x, y, w, h;
        sscanf(&p_line_buf[iread], "%d %d %d %d", &x, &y, &w, &h);
        CvRect rc;
        rc.x = x;
        rc.y = y;
        rc.width = w;
        rc.height = h;
    }

    return 0;
}
#endif

void im_export(const CvMat *pimsrc, FILE *p_file, CvRect rc)
{
#if 0
    const int32_t nsample = 7;
    fwrite(&nsample, 4, 1, p_file);
    int32_t i, j;
    for (j = 0; j < nsample; j++) {
        int32_t ss = round(rc.width*0.9f + rc.width*((rand()*0.2f / RAND_MAX)));
        int32_t dx = round(-ss*0.05f + ss*((rand()*0.1f / RAND_MAX)));
        int32_t dy = round(-ss*0.05f + ss*((rand()*0.1f / RAND_MAX)));

        int32_t topx = MAX(rc.x + dx, 0);
        int32_t topy = MAX(rc.y + dy, 0);
        int32_t botx = MIN(topx + ss, pimsrc->width - 1);
        int32_t boty = MIN(topy + ss, pimsrc->height - 1);

        int32_t subss = MIN(botx - topx, boty - topy);
        subss -= (subss & 3);
        CvRect subrc = cvRect(topx, topy, subss, subss);

        int32_t mx = subrc.x + subss*0.5f;
        int32_t my = subrc.y + subss*0.5f;

        fwrite(&mx, 4, 1, p_file);
        fwrite(&my, 4, 1, p_file);
        fwrite(&subss, 4, 1, p_file);

#if 0
        CvMat submat;
        cvGetSubRect(pimsrc, &submat, subrc);
        cvShowImage("submat", &submat);
        cvWaitKey();
#endif
    }
    return;
#else
    const int32_t nsample = 1;
    fwrite(&nsample, 4, 1, p_file);

    int32_t topx = MAX(rc.x - 0.05f*rc.width, 0);
    int32_t topy = MAX(rc.y - 0.05f*rc.height, 0);
    int32_t botx = MIN(topx + rc.width + 0.1f*rc.width, pimsrc->width - 1);
    int32_t boty = MIN(topy + rc.height + 0.1f*rc.width, pimsrc->height - 1);
    int32_t subss = MIN(botx - topx, boty - topy);
    subss -= (subss & 3);
    CvRect subrc = cvRect(topx, topy, subss, subss);
    int32_t mx = subrc.x + subss*0.5f;
    int32_t my = subrc.y + subss*0.5f;
    int32_t ss = subrc.width;  
    fwrite(&mx, 4, 1, p_file);
    fwrite(&my, 4, 1, p_file);
    fwrite(&ss, 4, 1, p_file);

#if 0
    CvMat submat;
    cvGetSubRect(pimsrc, &submat, subrc);
    cvShowImage("src", pimsrc);
    cvShowImage("submat", &submat);
    cvWaitKey();
#endif

    return;
#endif    
}

int main()
{
    FILE *fp_label  = fopen(STR_LABEL_LIST, "r");
    FILE *fp_sample = fopen(STR_OUTPUT_SAMPLE, "wb");

    if (!fp_label) {
        printf("ERROR:: \n");

        return -1;
    }
    int32_t iimg = 0;
    int32_t ipos = 0;
    int32_t ineg = 0;
    char filename[1024];
    while (fscanf(fp_label, "%s", filename) != EOF) {
        IplImage *pimshow = cvLoadImage(filename, CV_LOAD_IMAGE_COLOR);

        if (!pimshow) {
            printf("ERROR:: invalid file name!\n");
            return -1;
        }

        CvMat *pimsrc = cvCreateMat(pimshow->height, pimshow->width, CV_8UC1);
        cvCvtColor(pimshow, pimsrc, CV_BGR2GRAY);

        iimg++;

        int32_t num, n;
        fscanf(fp_label, "%d ", &num);
        for (n = 0; n < num; n++) {
            int32_t x, y, w, h;
            fscanf(fp_label, "%d %d %d %d", &x, &y, &w, &h);

            int32_t topx = MAX(x - 0.25f*w, 0);
            int32_t topy = MAX(y - 0.25f*w, 0);
            int32_t botx = MIN(x + 1.25f*w, pimsrc->width - 1);
            int32_t boty = MIN(y + 1.25f*w, pimsrc->height - 1);

            int32_t ss = MIN(botx - topx, boty - topy);
            ss -= (ss & 3);
            CvRect rc = cvRect(topx, topy, ss, ss);
            CvMat *p_submat = cvCreateMat(rc.height, rc.width, CV_8UC1), submat;
            cvGetSubRect(pimsrc, &submat, rc);
            cvCopy(&submat, p_submat);

            fwrite(&p_submat->width, 4, 1, fp_sample);
            fwrite(&p_submat->width, 4, 1, fp_sample);
            fwrite(p_submat->data.ptr, p_submat->width*p_submat->width, 1, fp_sample);

            CvRect rc_offset;
            rc_offset.x = x - rc.x;
            rc_offset.y = y - rc.y;
            rc_offset.width = w;
            rc_offset.height = h;

            im_export(p_submat, fp_sample, rc_offset);

            cvReleaseMat(&p_submat);

            ipos += 1;
        }
#if 0
        for (n = 0; n < num; n++) {
            int32_t x, y, w, h;

            CvRect rc = vec_rc[n];
            rc.x = pimsrc->width - (vec_rc[n].x + vec_rc[n].width);

            CvMat *p_submat = cvCreateMat(rc.height, rc.width, CV_8UC1), submat;
            cvGetSubRect(pimsrc_mirror, &submat, rc);
            cvCopy(&submat, p_submat);

            cvShowImage("submat", p_submat);
            cvWaitKey();

            fwrite(&p_submat->width, 4, 1, fp_sample);
            fwrite(&p_submat->width, 4, 1, fp_sample);
            fwrite(p_submat->data.ptr, p_submat->width*p_submat->width, 1, fp_sample);

            CvRect rc_label = vec_rc_label[n];
            rc_label.x = pimsrc->width - (vec_rc_label[n].x + vec_rc_label[n].width);
            CvRect rc_offset;
            rc_offset.x = rc_label.x - rc.x;
            rc_offset.y = rc_label.y - rc.y;
            rc_offset.width = rc_label.width;
            rc_offset.height = rc_label.height;

            im_export(p_submat, fp_sample, rc_offset);
            cvReleaseMat(&p_submat);
        }
#endif
#if 0
        cvShowImage("src", pimshow);
        cvWaitKey();
#endif
        cvReleaseImage(&pimshow);
        cvReleaseMat(&pimsrc);
        printf("%5d: done\n", ipos);
    }

    printf("===================\n ipos positive finished!!\n==================\n", ipos);

    fclose(fp_label);
    
    fp_label = fopen(STR_NEGATIVE_LIST, "r");
    while (fscanf(fp_label, "%s", filename) != EOF) {
        IplImage *pimshow = cvLoadImage(filename, CV_LOAD_IMAGE_COLOR);

        if (!pimshow) {
            printf("ERROR:: invalid file name!\n");
            break;
        }

        CvMat *pimsrc = cvCreateMat(pimshow->height, pimshow->width, CV_8UC1);
        cvCvtColor(pimshow, pimsrc, CV_BGR2GRAY);

        iimg++;
        ineg++;

        int32_t w = pimsrc->cols;
        int32_t h = pimsrc->rows;
        fwrite(&w, 4, 1, fp_sample);
        fwrite(&h, 4, 1, fp_sample);
        fwrite(pimsrc->data.ptr, w*h, 1, fp_sample);
        int32_t itemp = 0;
        fwrite(&itemp, 4, 1, fp_sample);
        cvReleaseImage(&pimshow);
        cvReleaseMat(&pimsrc);
        //fflush(fp_sample);

        if (iimg == 300) {
            //break;
        }
    }

    fclose(fp_label);
    fclose(fp_sample);

    printf("===================\n %d negative finished!!\n==================\n", ineg);

    return 0;
}